package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.model.domain.Question;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.dto.RecommendUserDto;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.NearUserVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.TodayBest;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.service.*;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author げっしょく
 * @date 2021/10/25
 */
@Service
public class TanhuaService {

    @DubboReference(timeout = 20000)
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionApi questionApi;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @DubboReference
    private UserLikeApi userLikeApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private MessagesService messagesService;

    @DubboReference
    private UserLocationApi userLocationApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    @Value("tanhua.default.recommend.users")
    private String users;



    public TodayBest todayBest() {
        Long id = UserHolder.getId();
        RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(id);
        if (recommendUser == null) {
            recommendUser.setScore(99d);
            recommendUser.setToUserId(UserHolder.getId());
            recommendUser.setUserId(1L);
        }
        Long userId = recommendUser.getUserId();
        UserInfo userInfo = userInfoApi.getUserById(userId);

        TodayBest todayBest = TodayBest.init(userInfo, recommendUser);

        return todayBest;
    }

    /**
     * 首页的推荐用户
     * @param recommendUserDto 页码，条数，推荐条件
     * @return 通过条件查询到的数据
     */
    public PageResult recommendation(RecommendUserDto recommendUserDto) {
        Long toUserId = UserHolder.getId();
        PageResult pr = recommendUserApi.queryRecommendUserList(toUserId, recommendUserDto.getPage(), recommendUserDto.getPagesize());
        if (pr == null) {
            return pr;
        }
        List<RecommendUser> items = (List<RecommendUser>) pr.getItems();
        List<Long> userIds = items.stream().map(r -> r.getUserId()).collect(Collectors.toList());
        UserInfo userInfo = new UserInfo();
        userInfo.setAge(recommendUserDto.getAge());
        userInfo.setGender(recommendUserDto.getGender());
        Map map = userInfoApi.getByUserIds(userIds, userInfo);
        List<TodayBest> list = new ArrayList<>();
        for (RecommendUser item : items) {
            UserInfo userInfo1 = (UserInfo) map.get(item.getUserId());
            if (userInfo1 != null) {
                TodayBest todayBest = TodayBest.init(userInfo1, item);
                list.add(todayBest);
            }
        }
        pr.setItems(list);
        return pr;
    }

    //查询推荐好友的详细信息和缘分值
    public TodayBest getUserInfo(Long id) {

        //通过用户id去查询对应的用户详情
        UserInfo userInfo = userInfoApi.getUserById(id);
        //通过用户id和操作人id去查询对应的缘分值
        RecommendUser recommendUser = recommendUserApi.getUserScore(id, UserHolder.getId());
        //判断访问人和用户是否是自己,是自己就不保存
        if (id != UserHolder.getId()) {
            //保存访客
            Visitors visitors = new Visitors();
            visitors.setScore(recommendUser.getScore());
            visitors.setUserId(recommendUser.getUserId());
            visitors.setVisitorUserId(UserHolder.getId());
            visitorsApi.saveVisitor(visitors);
        }
        //封装成vo返回
        TodayBest init = TodayBest.init(userInfo, recommendUser);
        return init;
    }

    //查询用户的陌生人问题
    public String getQuestion(Long userId) {
        //通过用户id获取出验证码
        Question question = questionApi.getById(userId);
        if (question == null) {
            //不要使用question进行设置,,因为设置就会出错,空指针异常
            return  "你愿意我和一起学习穿搭吗?";
        }
        //返回验证码
        return question.getTxt();
    }

    //回复陌生人消息
    public void sendMessage(Long userId, String reply) {
        //查询操作用户的详细信息
        Long id = UserHolder.getId();
        UserInfo userInfo = userInfoApi.getUserById(id);
        //查找回复人的环信账号(规则: hx + {userId})
        
        Map map = new HashMap();
        map.put("userId", id);
        map.put("huanXinId", Constants.HX_USER_PREFIX + id);
        map.put("nickname", userInfo.getNickname());
        //通过方法找陌生人信息,是因为从数据库中查找会有可能没有设置陌生人问题的
        //没有设置,然后在给其中设置设置默认陌生人问题就会报空指针异常
        map.put("strangerQuestion", getQuestion(userId));
        map.put("reply", reply);
        String context = JSON.toJSONString(map);

        //发送消息
        //发送消息第一参数是接受消息人的环信id,
        huanXinTemplate.sendMsg(Constants.HX_USER_PREFIX + userId, context);


    }

    //探花功能中的推荐
    public List<TodayBest> cards() {
        //从推荐列表中查询推荐好友(排除已经喜欢了或者不喜欢的)
        List<RecommendUser> recommendUsers = recommendUserApi.getRecommendFriend(UserHolder.getId());
        //判断推荐好友是否为空
        if (CollUtil.isEmpty(recommendUsers)) {
            String[] split = users.split(",");
            for (String s : split) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(Long.valueOf(s));
                recommendUser.setToUserId(UserHolder.getId());
                recommendUser.setScore(RandomUtil.randomDouble(60,90));
                recommendUsers.add(recommendUser);
            }

        }
        //不为空,取出对应的userId
        List<Long> userId = CollUtil.getFieldValues(recommendUsers, "userId", Long.class);
        //拿userId去查询对应的用户详情
        Map<Long, UserInfo> map = userInfoApi.getByUserIds(userId, null);
        //放回数据
        List<TodayBest> list = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUsers) {
            UserInfo userInfo = map.get(recommendUser.getUserId());
            if (userInfo != null) {
                TodayBest t = TodayBest.init(userInfo, recommendUser);
                list.add(t);
            }
        }

        return list;
    }

    //喜欢和不喜欢
    public void saveOrUpdate(Long likeUserId, boolean b) {
        //获得操作人id
        Long userId = UserHolder.getId();
        //调用方法进行喜欢或者不喜欢操作
        Boolean aBoolean =userLikeApi.saveOrUpdate(userId, likeUserId, b);
        //判断操作是否成功
        if (!aBoolean) {
            throw new BusinessException(ErrorResult.error());
        }

        if (b) {
            //如果是喜欢操作,删除redis中的不喜欢的缓存数据,添加一条喜欢数据
            redisTemplate.opsForSet().remove(Constants.USER_NOT_LIKE_KEY + UserHolder.getId(), likeUserId.toString());
            redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY + UserHolder.getId(), likeUserId.toString());
            //如果双方是互相喜欢,就成为好友
            if (redisTemplate.opsForSet().isMember(Constants.USER_LIKE_KEY + likeUserId, UserHolder.getId().toString())) {
                messagesService.addFriend(likeUserId);
            }
        } else {
            //判断是否是互相喜欢,就删除好友
            if (redisTemplate.opsForSet().isMember(Constants.USER_LIKE_KEY + likeUserId, UserHolder.getId().toString()) &&
                    redisTemplate.opsForSet().isMember(Constants.USER_LIKE_KEY + UserHolder.getId(), likeUserId.toString()) ) {
                messagesService.deleteFriend(likeUserId);
            }
            //如果是不喜欢操作,删除redis中的喜欢的缓存数据,添加一条不喜欢数据
            redisTemplate.opsForSet().remove(Constants.USER_LIKE_KEY  + UserHolder.getId(), likeUserId.toString());
            redisTemplate.opsForSet().add(Constants.USER_NOT_LIKE_KEY + UserHolder.getId(), likeUserId.toString());

        }



    }

    public List<NearUserVo> queryNearby(String gender, String distance) {
        //查询出附近的人的id
        List<Long> ids = userLocationApi.queryNearby(UserHolder.getId(), Double.valueOf(distance));
        //判断id集合是否为空
        List<NearUserVo> vos = new ArrayList<>();
        if (CollUtil.isEmpty(ids)) {
            return vos;
        }
        //根据集合和条件进行查询用户详情
        UserInfo userInfo = new UserInfo();
        userInfo.setGender(gender);
        Map<Long, UserInfo> map = userInfoApi.getByUserIds(ids, userInfo);
        //封装vo
        for (Long id : ids) {
            if (id == UserHolder.getId()) {
                continue;
            }
            UserInfo userInfo1 = map.get(id);
            if (userInfo1 != null) {
                NearUserVo vo = NearUserVo.init(userInfo1);
                vos.add(vo);
            }
        }
        return vos;
    }
}
